// SPDX-License-Identifier: GPL-2.0
#ifndef _NF_SPECIAL_TRACE_H
#define _NF_SPECIAL_TRACE_H

#include <linux/netfilter/nf_conntrack_sip.h>
#include <linux/netfilter/nf_conntrack_ftp.h>
#include <linux/netfilter/nf_conntrack_tftp.h>
#include <linux/netfilter/nf_conntrack_h323_types.h>

#ifdef CONFIG_NF_CT_ALG_DEBUG

struct msg_type {
	int type;
	const char *msg;
};

#define UNDEF_TYPE (-1)
#define DEF_UND_TYPE                { UNDEF_TYPE, "unknown" }
#define DEF_MSG_TYPE(prefix, type)  { prefix##_##type, #type }

static inline const char *msg_from_type(struct msg_type *map, int cnt, int type)
{
	int i;

	for (i = 1; i < cnt; i++) {
		if (map[i].type == type)
			return map[i].msg;
	}

	return map[0].msg;
}

#define SIP_DMSG(msg) (msg)

static inline const char *sip_hdrmsg(enum sip_header_types type)
{
	if (type == SIP_HDR_FROM)
		return "From";

	if (type == SIP_HDR_TO)
		return "To";

	return "";
}

static inline const char *sdp_hdrmsg(enum sdp_header_types type)
{
	struct msg_type map[] = {
		{ UNDEF_TYPE, "" },
		{ SDP_HDR_UNSPEC, "" },
		{ SDP_HDR_VERSION, "Version" },
		{ SDP_HDR_OWNER, "Owner Address" },
		{ SDP_HDR_CONNECTION, "Connection Address" },
		{ SDP_HDR_MEDIA, "Media port" },
	};

	return msg_from_type(map, ARRAY_SIZE(map), type);
}

static inline const char *ftp_msgtype(enum nf_ct_ftp_type type)
{
	struct msg_type map[] = {
		{ UNDEF_TYPE, "" },
		{ NF_CT_FTP_PORT, "PORT" },
		{ NF_CT_FTP_EPRT, "EPRT" },
		{ NF_CT_FTP_PASV, "Passive Mode (227)" },
		{ NF_CT_FTP_EPSV, "Passive Mode (229)" },
	};

	return msg_from_type(map, ARRAY_SIZE(map), type);
}

static inline const char *tftp_msgtype(int type)
{
	struct msg_type map[] = {
		{ UNDEF_TYPE, "Unknown" },
		{ TFTP_OPCODE_READ, "Read" },
		{ TFTP_OPCODE_WRITE, "Write" },
		{ TFTP_OPCODE_DATA, "Data" },
		{ TFTP_OPCODE_ACK, "ACK" },
		{ TFTP_OPCODE_ERROR, "Error" }
	};

	return msg_from_type(map, ARRAY_SIZE(map), type);
}

/* RequestMessage.choice - eRequestMessage_nonStandard, etc.
 * Convert enum types to msg strings. for example:
 *     { eRequestMessage_nonStandard, "nonStandard" }
 */
static inline const char *h245_reqmsg(int type)
{
	struct msg_type map[] = {
		DEF_UND_TYPE,
		DEF_MSG_TYPE(eRequestMessage, nonStandard),
		DEF_MSG_TYPE(eRequestMessage, masterSlaveDetermination),
		DEF_MSG_TYPE(eRequestMessage, terminalCapabilitySet),
		DEF_MSG_TYPE(eRequestMessage, openLogicalChannel),
		DEF_MSG_TYPE(eRequestMessage, closeLogicalChannel),
		DEF_MSG_TYPE(eRequestMessage, requestChannelClose),
		DEF_MSG_TYPE(eRequestMessage, multiplexEntrySend),
		DEF_MSG_TYPE(eRequestMessage, requestMultiplexEntry),
		DEF_MSG_TYPE(eRequestMessage, requestMode),
		DEF_MSG_TYPE(eRequestMessage, roundTripDelayRequest),
		DEF_MSG_TYPE(eRequestMessage, maintenanceLoopRequest),
		DEF_MSG_TYPE(eRequestMessage, communicationModeRequest),
		DEF_MSG_TYPE(eRequestMessage, conferenceRequest),
		DEF_MSG_TYPE(eRequestMessage, multilinkRequest),
		DEF_MSG_TYPE(eRequestMessage, logicalChannelRateRequest),
	};

	return msg_from_type(map, ARRAY_SIZE(map), type);
}

/* ResponseMessage.choice - eResponseMessage_nonStandard, etc.
 * Convert enum types to msg strings. for example:
 *     { eResponseMessage_nonStandard, "nonStandard" }
 */
static inline const char *h245_rspmsg(int type)
{
	struct msg_type map[] = {
		DEF_UND_TYPE,
		DEF_MSG_TYPE(eResponseMessage, nonStandard),
		DEF_MSG_TYPE(eResponseMessage, masterSlaveDeterminationAck),
		DEF_MSG_TYPE(eResponseMessage, masterSlaveDeterminationReject),
		DEF_MSG_TYPE(eResponseMessage, terminalCapabilitySetAck),
		DEF_MSG_TYPE(eResponseMessage, terminalCapabilitySetReject),
		DEF_MSG_TYPE(eResponseMessage, openLogicalChannelAck),
		DEF_MSG_TYPE(eResponseMessage, openLogicalChannelReject),
		DEF_MSG_TYPE(eResponseMessage, closeLogicalChannelAck),
		DEF_MSG_TYPE(eResponseMessage, requestChannelCloseAck),
		DEF_MSG_TYPE(eResponseMessage, requestChannelCloseReject),
		DEF_MSG_TYPE(eResponseMessage, multiplexEntrySendAck),
		DEF_MSG_TYPE(eResponseMessage, multiplexEntrySendReject),
		DEF_MSG_TYPE(eResponseMessage, requestMultiplexEntryAck),
		DEF_MSG_TYPE(eResponseMessage, requestMultiplexEntryReject),
		DEF_MSG_TYPE(eResponseMessage, requestModeAck),
		DEF_MSG_TYPE(eResponseMessage, requestModeReject),
		DEF_MSG_TYPE(eResponseMessage, roundTripDelayResponse),
		DEF_MSG_TYPE(eResponseMessage, maintenanceLoopAck),
		DEF_MSG_TYPE(eResponseMessage, maintenanceLoopReject),
		DEF_MSG_TYPE(eResponseMessage, communicationModeResponse),
		DEF_MSG_TYPE(eResponseMessage, conferenceResponse),
		DEF_MSG_TYPE(eResponseMessage, multilinkResponse),
		DEF_MSG_TYPE(eResponseMessage, logicalChannelRateAcknowledge),
		DEF_MSG_TYPE(eResponseMessage, logicalChannelRateReject),
	};

	return msg_from_type(map, ARRAY_SIZE(map), type);
}

/* H323_UU_PDU_h323_message_body.choice - eH323_UU_PDU_h323_message_body_setup, etc.
 * Convert enum types to msg strings. for example:
 *     { eH323_UU_PDU_h323_message_body_setup, "setup" }
 */
static inline const char *q931_msgtype(int type)
{
	struct msg_type map[] = {
		DEF_UND_TYPE,
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, setup),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, callProceeding),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, connect),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, alerting),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, information),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, releaseComplete),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, facility),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, progress),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, empty),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, status),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, statusInquiry),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, setupAcknowledge),
		DEF_MSG_TYPE(eH323_UU_PDU_h323_message_body, notify),
	};

	return msg_from_type(map, ARRAY_SIZE(map), type);
}

/* RasMessage.choice - eRasMessage_gatekeeperRequest, etc.
 * Convert enum types to msg strings. for example:
 *     { eRasMessage_gatekeeperRequest, "gatekeeperRequest" }
 */
static inline const char *ras_msgtype(int type)
{
	struct msg_type map[] = {
		DEF_UND_TYPE,
		DEF_MSG_TYPE(eRasMessage, gatekeeperRequest),
		DEF_MSG_TYPE(eRasMessage, gatekeeperConfirm),
		DEF_MSG_TYPE(eRasMessage, gatekeeperReject),
		DEF_MSG_TYPE(eRasMessage, registrationRequest),
		DEF_MSG_TYPE(eRasMessage, registrationConfirm),
		DEF_MSG_TYPE(eRasMessage, registrationReject),
		DEF_MSG_TYPE(eRasMessage, unregistrationRequest),
		DEF_MSG_TYPE(eRasMessage, unregistrationConfirm),
		DEF_MSG_TYPE(eRasMessage, unregistrationReject),
		DEF_MSG_TYPE(eRasMessage, admissionRequest),
		DEF_MSG_TYPE(eRasMessage, admissionConfirm),
		DEF_MSG_TYPE(eRasMessage, admissionReject),
		DEF_MSG_TYPE(eRasMessage, bandwidthRequest),
		DEF_MSG_TYPE(eRasMessage, bandwidthConfirm),
		DEF_MSG_TYPE(eRasMessage, bandwidthReject),
		DEF_MSG_TYPE(eRasMessage, disengageRequest),
		DEF_MSG_TYPE(eRasMessage, disengageConfirm),
		DEF_MSG_TYPE(eRasMessage, disengageReject),
		DEF_MSG_TYPE(eRasMessage, locationRequest),
		DEF_MSG_TYPE(eRasMessage, locationConfirm),
		DEF_MSG_TYPE(eRasMessage, locationReject),
		DEF_MSG_TYPE(eRasMessage, infoRequest),
		DEF_MSG_TYPE(eRasMessage, infoRequestResponse),
		DEF_MSG_TYPE(eRasMessage, nonStandardMessage),
		DEF_MSG_TYPE(eRasMessage, unknownMessageResponse),
		DEF_MSG_TYPE(eRasMessage, requestInProgress),
		DEF_MSG_TYPE(eRasMessage, resourcesAvailableIndicate),
		DEF_MSG_TYPE(eRasMessage, resourcesAvailableConfirm),
		DEF_MSG_TYPE(eRasMessage, infoRequestAck),
		DEF_MSG_TYPE(eRasMessage, infoRequestNak),
		DEF_MSG_TYPE(eRasMessage, serviceControlIndication),
		DEF_MSG_TYPE(eRasMessage, serviceControlResponse),
	};

	return msg_from_type(map, ARRAY_SIZE(map), type);
}

#else /* CONFIG_NF_CT_ALG_DEBUG */

#define SIP_DMSG(msg) ""

static inline const char *sip_hdrmsg(enum sip_header_types type)
{
	return "";
}

static inline const char *sdp_hdrmsg(enum sdp_header_types type)
{
	return "";
}

static inline const char *ftp_msgtype(enum nf_ct_ftp_type type)
{
	return "";
}

static inline const char *tftp_msgtype(int type)
{
	return "";
}

static inline const char *h245_reqmsg(int type)
{
	return "";
}

static inline const char *h245_rspmsg(int type)
{
	return "";
}

static inline const char *q931_msgtype(int type)
{
	return "";
}

static inline const char *ras_msgtype(int type)
{
	return "";
}

#endif /* CONFIG_NF_CT_ALG_DEBUG */

#endif /* _NF_SPECIAL_TRACE_H */
